package com.fx.securityConfig;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fx.demo.common.RsaTools;
import com.fx.entity.User;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.PrivateKey;
import java.util.Collection;
import java.util.Date;

/**
 * des:
 *
 * @author fxiao
 * @date 2020/12/15 12:52
 */
public class JwtLoginFilter extends AbstractAuthenticationProcessingFilter {
    public JwtLoginFilter(String defaultFilterProcessesUrl, AuthenticationManager authenticationManager) {
        super(new AntPathRequestMatcher(defaultFilterProcessesUrl));
        setAuthenticationManager(authenticationManager);
    }

    /**
     * 从登录请求中获取用户名密码
     * @param req
     * @param resp
     * @return
     * @throws AuthenticationException
     * @throws IOException
     */
    @Override
    public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse resp) throws AuthenticationException, IOException{
        User user=new ObjectMapper().readValue(req.getInputStream(),User.class);
        return getAuthenticationManager().authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()));
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse resp, FilterChain chain, Authentication authResult) throws IOException{
        Collection<? extends GrantedAuthority> authorities = authResult.getAuthorities();
        StringBuffer as = new StringBuffer();
        for (GrantedAuthority authority : authorities) {
            as.append(authority.getAuthority())
                    .append(",");
        }
        PrivateKey privateKey= RsaTools.parsePrivateKey(
                "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDDCyhPxtNT5LSG85LHBWmoqXYELAjrdLQUfnH68yWnbM2+e9H3kkclM5+KLlnb6gHPjKjbwSGNpvjgMu3n3Eo+Urebgf9p879xEsDKTVQuNZnqvqWDRlgBb0qHK795Ovrp6WgDsTFx22NAJYbF9l7XpvQ2ZONv1uhLyqv2wKQGjA4Mbc6AEqL5x9sPrnpfPcOQhAgabZTAtVWtyAzW5xwYQEAmZNJx+KsgKvtzChkQsXMowvVK//DmTU5Dpm36rUF918rfRKgSWPs0FzUJ6acjdaePyIwwO9DTUeFb7eG6ZAZBCdKwFenSwRTh6+ibuLuWJs3yGcxouY5iJ0id+zXRAgMBAAECggEAZSOkA7pWW2p9Mn2b3xgvcgZt7DvpZC9gMkBfWoI7RFZnWh9bAcYYnnHmiQEAF8mApt+JsGq1u36aD6hZNaJF3YuHKlx+1bJP05Kl5kGzJUMmTVQO/8O6XwQW4YEOCQ9MjX87MK7xtNjO3rSW7pCTHcC1Yn9ucNBAJQ0znwDGDZ4q4q8E0om2/E/EAl+5GC4/Vl6+y1bazcxqFygoZKL8A3ZPNX8cyh8S7p3KCocdJ0WM60NDmHlzhaFNOzhvU+ODyotDTXU8NNBeZ7uWDl3Bs3d3bFejfOGbdPMAPdhmPaMt7dsw7ArX0i6x53bEkush+9/jzp7FsAcIhUpbGMowAQKBgQDjddw6nqxW6Hk2k8fCPI51t1clGQMd64KJfcXZ8xOFKHTpvuEnHkv/S/mAEsyw+4WfucjshemKIFX3GLeEdg4M9Qnh5P38CArwVkBbXVpwOdIcnxwNtlpSh6XvH+6VAZsFfjGzTgw3XKKAUOT7U3dBUXSsat7SgZUWVp5HEUxx6QKBgQDbhA2qC7c4QXeej+FzQT5QOV7d3g8O5zkgSeevqOxpz5iTTV9fkO77wYGRP88vzwEB1JRwNuM1H3tL3UVfD1PRWuP7l/tj46Qx+haBX4OF2UxwovDVlVKbDV7j4p8Wj0C4UP9sd0hXmzFaEHrIkai7ipZpfohxWsC6e7l0gkcLqQKBgCPE6wcE4NEh6b3da3JuF3EHjdq1njncSUDZ2H03roAoJoqDi+Cc8RKKnge37Rx/0TmW+7PGMz2XbC1ZY7Ke5gK/nfg6DH7PvPiid6hme8xeK1543u6BGJ8V2dBK0zf3cqtgduxdf6pNFPjcv8WOEJji+FgMzlGIMyu6H1XJsJ3RAoGBAJYRQdIlLj1sLB2fGS5UxQfNILimrT6v/hK/0374CZ8Qh6rz8yZ/C5HaqPwmVjrF1lds/4lzTIKtofmsLFefP9rYuxDtxrN0FXUBFk+df2mKs0IxcllhOta7HkrGS6H9ju4ymVuKdE9HzkZXC8mAIo0LYmZ+VULBGw6htJgc0/r5AoGAXxfeFgCdMBOQYKK93Z3fdZpN9624AL9CM6jIT3WHWL+3B3hl7O0/iMH2No+vS0vpRveTjJChRsqf/6QSoOBfnouKHl6YEh4Pm91TxW+F9GlT2sF5kG1o6xMQwXz1yDwo39WGuhO9CfkBH68uYLrseu7eMXFu5kl+CsMhSdfyMg0="
                );
        String jwt = Jwts.builder()
                .claim("authorities", as)//配置用户角色
                .setSubject(authResult.getName())
                //十分钟
                .setExpiration(new Date(System.currentTimeMillis() + 10 * 60 * 1000))
                //指定加密算法和密钥
                .signWith(SignatureAlgorithm.RS256,privateKey)
                .compact();
        resp.setContentType("application/json;charset=utf-8");
        PrintWriter out = resp.getWriter();
        out.write(new ObjectMapper().writeValueAsString(jwt));
        out.flush();
        out.close();
    }

    protected void unsuccessfulAuthentication(HttpServletRequest req, HttpServletResponse resp, AuthenticationException e) throws IOException{

        resp.setContentType("application/json;charset=utf-8");
        PrintWriter out = resp.getWriter();
        String message = "";
        if (e instanceof LockedException) {
            message = "账户被锁定，请联系管理员!";
        } else if (e instanceof CredentialsExpiredException) {
            message = "密码过期，请联系管理员!";
        } else if (e instanceof AccountExpiredException) {
            message = "账户过期，请联系管理员!";
        } else if (e instanceof DisabledException) {
            message = "账户被禁用，请联系管理员!";
        } else if (e instanceof BadCredentialsException) {
            message = "用户名或者密码输入错误，请重新输入!";
        }
        out.write(new ObjectMapper().writeValueAsString(message));
        out.flush();
        out.close();
    }
}
